home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * *
- * Preliminary *
- * Amiga AppShell (tm) *
- * *
- * Copyright (c) 1990,1991 Commodore-Amiga, Inc. All Rights Reserved. *
- * *
- * This software and information is proprietary, preliminary, and *
- * subject to change without notice. *
- * *
- * DISCLAIMER *
- * *
- * THIS SOFTWARE IS PROVIDED "AS IS". *
- * NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE *
- * ACCURACY, RELIABILITY, PERFORMANCE, CURRENTNESS, OR OPERATION *
- * OF THIS SOFTWARE, AND ALL USE IS AT YOUR OWN RISK. *
- * NEITHER COMMODORE NOR THE AUTHORS ASSUME ANY RESPONSIBILITY OR *
- * LIABILITY WHATSOEVER WITH RESPECT TO YOUR USE OF THIS SOFTWARE. *
- * *
- * Non-Disclosure *
- * *
- * This information is not to be disclosed to any other company, *
- * individual or party. Discussion is to be restricted to CBM *
- * approved discussion areas, such as the closed conferences on bix; *
- * amiga.cert, amiga.com, amiga.beta/appshell. *
- * *
- ************************************************************************
- * multiproj.c
- * Copyright (C) 1991 Commodore-Amiga, Inc.
- * Minimum requirements for an AppShell application.
- * Written by David N. Junod
- *
- * Must be compiled with Lattice options: -b0 -cfist -ms -v
- *
- */
-
- #include "multiproj.h"
- #include "multiproj_rev.h"
-
- #define DI(x) ;
-
- void kprintf(void *, ...);
-
- /* Private functions */
- BOOL start_project (struct AppInfo * ai, struct ProjNode * pn);
- VOID signal_projects (struct AppInfo *, LONG, VOID (*func) (struct AppInfo *, struct ProjData *));
- BOOL SafePutToPort (struct Message * message, STRPTR name);
-
- /* Shell argument template */
- #define TEMPLATE "Files/M,BG=Background/S,UnLoad/S"
- #define OPT_FILES 0
- #define OPT_BACKG 1
- #define OPT_UNLOAD 2
- #define OPT_COUNT 3
-
- /* All text used in the application must be defined in a text array. Then
- * referred to by numeric ID. */
- STRPTR MasterText[] =
- {
- /* Padding */
- "",
-
- "Not enough memory",
- "Couldn't allocate project",
- "Couldn't start project process",
- "Master port went away",
- "Can't allocate images",
-
- /* NULL termination is required */
- NULL
- };
-
- #define MPERR_NO_MEMORY 1
- #define MPERR_NO_PROJECT 2
- #define MPERR_NO_PROCESS 3
- #define MPERR_NO_PORT 4
-
- /* The AppShell will convert this array into function table entries and will
- * add them to the function table list. Using the APSHF_PRIVATE flag, we are
- * able to have functions that can't be triggered by the user. This
- * also defines the commands that are available through ARexx. Note that
- * the command parser is case-INSENSITIVE, but for readability, your
- * entries in this table should follow standard capitalization rules. */
- struct Funcs MasterFuncTable[] =
- {
- /* These are public master functions */
- {"Quit", QuitFunc, QuitID, "FORCE/S,UNLOAD/S", 2L, NULL,},
- {"New", NewFunc, NewID,},
-
- /* This function can not be accessed by the user */
- {"CInit", CInitFunc, CInitID, NULL, NULL, APSHF_PRIVATE},
- {"CExit", CExitFunc, CExitID, NULL, NULL, APSHF_PRIVATE},
- {"IsActive", IsActiveFunc, IsActiveID, NULL, NULL, APSHF_PRIVATE},
- {"Open", OpenFunc, OpenID, NULL, NULL, APSHF_PRIVATE,},
- {"Close", CloseFunc, CloseID, NULL, NULL, APSHF_PRIVATE,},
- {"ActiveTool", ActiveToolFunc, ActiveToolID, NULL, NULL, APSHF_PRIVATE,},
- {"SetAttrs", SetAttrsFunc, SetAttrsID, "BACKGROUND/S,UNLOAD/S", 2, NULL,},
-
- /* Marks the end of the array */
- {NULL, NO_FUNCTION,}
- };
-
- /* Shared system libraries */
- struct Library *AslBase;
- struct Library *GadToolsBase;
- struct Library *GfxBase;
- struct Library *IconBase;
- struct Library *IntuitionBase;
- struct Library *UtilityBase;
- struct Library *AppObjectsBase;
-
- /* Library Environment:
- * This tag array is used to open and close the shared system libraries
- * needed by our application.
- */
- struct TagItem Our_Libs[] =
- {
- /* Minimum library version */
- {APSH_LibVersion, 36L},
-
- /* All libraries are required */
- {APSH_LibStatus, APSH_REQUIRED},
-
- /* Libraries to open */
- {APSH_ASL, (ULONG) & AslBase},
- {APSH_GadTools, (ULONG) & GadToolsBase},
- {APSH_Gfx, (ULONG) & GfxBase},
- {APSH_Icon, (ULONG) & IconBase},
- {APSH_Intuition, (ULONG) & IntuitionBase},
- {APSH_Utility, (ULONG) & UtilityBase},
-
- /* The next library is optional */
- {APSH_LibStatus, APSH_OPTIONAL},
- {APSH_LibName, (ULONG) "appobjects.library"},
- {APSH_LibBase, (ULONG) & AppObjectsBase},
- {TAG_DONE,}
- };
-
- /* ARexx user interface environment specification array */
- static struct TagItem Handle_AREXX[] =
- {
- {APSH_Extens, (ULONG) "skel"},
- {APSH_Status, APSHP_SINGLE},
- {APSH_Rating, APSH_OPTIONAL},
- {TAG_DONE,}
- };
-
- /* These tags describe the Simple IPC user interface. */
- static struct TagItem Handle_SIPC[] =
- {
- {APSH_Status, APSHP_SINGLE},
- {APSH_Rating, APSH_REQUIRED},
- {APSH_AlreadyRunning, IsActiveID},
- {TAG_DONE,}
- };
-
- /* These tags describe the Asynchronous Tool user interface */
- struct TagItem Handle_Tool[] =
- {
- {APSH_Rating, APSH_REQUIRED},
- {TAG_DONE,}
- };
-
- /* Application Environment:
- * Tell about the master server application */
- struct TagItem Our_App[] =
- {
- /* About the application */
- {APSH_AppName, (ULONG) APPNAME},
- {APSH_AppVersion, (ULONG) APPVERS},
- {APSH_AppCopyright, (ULONG) APPCOPY},
- {APSH_AppAuthor, (ULONG) APPAUTH},
-
- /* Trigger the library opening module */
- {APSH_OpenLibraries, (ULONG) Our_Libs},
-
- /* Specify the application function table */
- {APSH_FuncTable, (ULONG) MasterFuncTable},
-
- /* Specify the application text table */
- {APSH_DefText, (ULONG) MasterText},
-
- /* Tell how memory we need for our own data */
- {APSH_UserDataSize, sizeof (struct MasterData)},
-
- /* Give our Shell startup argument template */
- {APSH_Template, (ULONG) TEMPLATE},
- {APSH_NumOpts, (ULONG) OPT_COUNT},
-
- /* Must always specify the SIPC user interface */
- {APSH_AddSIPC_UI, (ULONG) Handle_SIPC},
-
- /* Add the Asynchronous tool user interface */
- {APSH_AddTool_UI, (ULONG) Handle_Tool},
-
- /* Add an ARexx user interface */
- {APSH_AddARexx_UI, (ULONG) Handle_AREXX},
-
- /* Specify a custom initialization routine */
- {APSH_AppInit, CInitID},
- {APSH_AppExit, CExitID},
-
- {TAG_DONE,}
- };
-
- /* handle messages between function handlers */
- BOOL HandlerFunc (struct AppInfo * ai, ULONG tags,...)
- {
- return (HandlerFuncA (ai, (struct TagItem *) & tags));
- }
-
- /* get handler data */
- APTR HandlerData (struct AppInfo * ai, ULONG tags,...)
- {
- return (HandlerDataA (ai, (struct TagItem *) & tags));
- }
-
- /* This is the initialization routine for the master server for the
- * application. */
- VOID CInitFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
- {
- struct MasterData *md = (struct MasterData *) ai->ai_UserData;
- struct Project *p = &(ai->ai_Project);
- struct List *list = &(p->p_ProjList);
- struct ProjNode *pn = NULL;
- struct MsgHandler *mh;
-
- /* Check the options */
- DI (kprintf ("CInitFunc enter\n"));
- if (ai->ai_Options[OPT_BACKG])
- {
- md->md_Flags |= MADF_BACKG;
- }
- if (ai->ai_Options[OPT_UNLOAD])
- {
- md->md_Flags &= ~MADF_BACKG;
- }
-
- /* Get a handle on our SIPC port */
- if (mh = HandlerData (ai, APSH_Handler, "SIPC", TAG_DONE))
- {
- /* Cache the pointer */
- md->md_SIPC = mh->mh_Port;
- }
-
- /* Make sure there are entries in the project list */
- if (list->lh_TailPred != (struct Node *) list)
- {
- struct Node *node, *nxtnode;
-
- /* Let's start at the very beginning... */
- node = list->lh_Head;
-
- /* Continue while there are still nodes */
- while ((ai->ai_Pri_Ret == RETURN_OK) &&
- ((nxtnode = node->ln_Succ)))
- {
- /* Start the project */
- start_project (ai, (struct ProjNode *) node);
-
- /* Go on to the next node */
- node = nxtnode;
- }
- }
- /*
- * No FILES/M parameters specified, see if they just want to load us in the
- * background.
- */
- else if (!(ai->ai_Options[OPT_BACKG]))
- {
- /* They want an new, blank project to work with. */
- if (pn = NewProject (ai, NULL, NULL))
- {
- /* Start the project */
- start_project (ai, pn);
- }
- /* Unable to allocate a new project */
- else
- {
- ai->ai_Pri_Ret = RETURN_FAIL;
- ai->ai_Sec_Ret = MPERR_NO_PROJECT;
- ai->ai_TextRtn =
- PrepText (ai, APSH_USER_ID, ai->ai_Sec_Ret, NULL);
- }
- }
- else
- {
- }
- DI (kprintf ("CInitFunc exit\n"));
- }
-
- VOID CExitFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
- {
- /* We don't really do anything in this example */
- }
-
- /* Open existing project */
- VOID OpenFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
- {
- struct Project *p = &(ai->ai_Project);
- struct List *list = &(p->p_ProjList);
- struct TagItem *attrs = af->af_Attrs;
- struct ProjNode *pn = NULL;
- LONG key;
-
- /* Lock the AppInfo structure */
- key = LockAppInfo (ai);
-
- /* Get a pointer to the project node */
- if (pn = (struct ProjNode *) GetTagData (APSH_ProjInfo, NULL, attrs))
- {
- /* Start the project */
- if (start_project (ai, pn))
- {
- /* Add the project to our list, so that it gets freed properly */
- AddTail (list, (struct Node *) pn);
-
- /* Adjust our project count accordingly */
- p->p_NumProjs++;
- }
- }
-
- /* Remove the lock */
- UnlockAppInfo (key);
- }
-
- /* Open existing project */
- VOID NewFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
- {
- struct ProjNode *pn;
-
- /* Create a new project */
- DI (kprintf ("NewFunc enter\n"));
- if (pn = NewProject (ai, NULL, NULL))
- {
- /* Start the project */
- start_project (ai, pn);
- }
- DI (kprintf ("NewFunc exit\n"));
- }
-
- /* Close an existing project */
- VOID CloseFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
- {
- struct MasterData *md = (struct MasterData *) ai->ai_UserData;
- struct Project *p = &(ai->ai_Project);
- struct TagItem *attrs = af->af_Attrs;
- struct ProjNode *pn;
- struct ProjData *pd;
- LONG key;
-
- /* Lock the master AppInfo */
- key = LockAppInfo (ai);
-
- /* Get a pointer to the project node */
- if (pn = (struct ProjNode *) GetTagData (APSH_ProjInfo, NULL, attrs))
- {
- /* Get the project data */
- if (pd = (struct ProjData *) pn->pn_UserData)
- {
- /* Free the extra tags */
- FreeTagItems (pd->pd_Clone);
-
- /* Free the project data */
- FreeVec (pd);
-
- /* Clear the UserData field */
- pn->pn_UserData = NULL;
- }
-
- /* Set the current project */
- p->p_CurProj = pn;
-
- /* Remove the project */
- RemoveProject (ai, NULL, NULL);
- }
-
- /* See if we should quit */
- if ((p->p_NumProjs <= 0L) && !(md->md_Flags & MADF_BACKG))
- {
- ai->ai_Done = TRUE;
- }
-
- /* Unlock the master AppInfo */
- UnlockAppInfo (key);
- }
-
- /* One of our projects just went active */
- VOID ActiveToolFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
- {
- struct TagItem *attrs = af->af_Attrs;
- struct ProjNode *pn;
- struct ProjData *pd;
- struct AppInfo *sai;
- struct MsgPort *smp;
- LONG key;
-
- /* Lock the AppInfo structure */
- key = LockAppInfo (ai);
-
- /* Get a pointer to the project node */
- if (pn = (struct ProjNode *) GetTagData (APSH_ProjInfo, NULL, attrs))
- {
- /* Cache the pointer to the Project data */
- pd = (struct ProjData *) pn->pn_UserData;
-
- /* Get the address of the projects AppInfo structure */
- if (sai = (struct AppInfo *) GetTagData (APSH_AppHandle, NULL, attrs))
- {
- /* Remember the project's AppInfo structure */
- pd->pd_AI = sai;
- }
-
- /* The address of the project's SIPC message port */
- if (smp = (struct MsgPort *) GetTagData (APSH_PortAddr, NULL, attrs))
- {
- /* Remember the message port */
- pd->pd_Port = smp->mp_Node.ln_Name;
- }
- }
-
- /* Remove the lock */
- UnlockAppInfo (key);
- }
-
- /* We are already running */
- VOID IsActiveFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
- {
- struct MasterData *md = (struct MasterData *) ai->ai_UserData;
- struct Project *p = &(ai->ai_Project);
- struct List *list = &(p->p_ProjList);
- struct TagItem *attrs = af->af_Attrs;
- struct SIPCMessage *msg;
- struct MsgPort *mp;
- BOOL going = TRUE;
- BOOL send = FALSE;
- STRPTR port_name;
-
- /* Get the name of our main port */
- DI (kprintf ("IsActiveFunc enter\n"));
- if (port_name = (STRPTR) GetTagData (APSH_NameTag, NULL, attrs))
- {
- DI (kprintf("PortName: %s\n", port_name));
-
- /* We need a reply port */
- if (mp = CreatePort (NULL, NULL))
- {
- /* Allocate a message */
- if (msg = (struct SIPCMessage *)
- AllocVec (sizeof (struct SIPCMessage), MEMF_PUBLIC | MEMF_CLEAR))
- {
- /* Fill out the Exec message */
- msg->sipc_Msg.mn_Node.ln_Type = NT_MESSAGE;
- msg->sipc_Msg.mn_Length = sizeof (struct SIPCMessage);
- msg->sipc_Msg.mn_ReplyPort = mp;
-
- /* Fill in the SIPC message portion */
- msg->sipc_Data = md->md_Tmp;
- msg->sipc_DType = APSH_SDT_Command;
-
- /* Initialize it */
- strcpy (md->md_Tmp, "SETATTRS ");
-
- /* See if they want us to unload */
- if (ai->ai_Options[OPT_UNLOAD])
- {
- /* Send UNLOAD */
- strcat (md->md_Tmp, "UNLOAD ");
- send = TRUE;
- }
-
- /* See if they want us to become sticky */
- if (ai->ai_Options[OPT_BACKG])
- {
- /* Send */
- strcat (md->md_Tmp, "BACKGROUND");
- send = TRUE;
- }
-
- /* Trying to set an option? */
- if (send)
- {
- /* Send the message */
- if (SafePutToPort ((struct Message *) msg, port_name))
- {
- /* wait for the reply */
- WaitPort (mp);
-
- /* Get the reply */
- GetMsg (mp);
- }
- }
- /* Make sure there are entries in the list */
- else if (list->lh_TailPred != (struct Node *) list)
- {
- struct Node *node, *nxtnode;
- struct TagItem tg[2];
-
- /* Prep the tag list */
- tg[0].ti_Tag = APSH_ProjInfo;
- tg[1].ti_Tag = TAG_DONE;
-
- /* Calling the Open command */
- msg->sipc_Type = OpenID;
-
- /* Show that we're passing tags */
- msg->sipc_DType = APSH_SDT_TagList;
- msg->sipc_Data = tg;
-
- /* Let's start at the very beginning... */
- node = list->lh_Head;
-
- /* Continue while there are still nodes */
- while (going && (nxtnode = node->ln_Succ))
- {
- /* Remove it from this list */
- Remove (node);
-
- /* Adjust our project count accordingly */
- p->p_NumProjs--;
-
- /* Point to it */
- tg[0].ti_Data = (ULONG) node;
-
- /* Send the message */
- if (SafePutToPort ((struct Message *) msg, port_name))
- {
- /* Wait for the reply */
- WaitPort (mp);
-
- /* Pull the message */
- GetMsg (mp);
- }
- else
- {
- /* Don't continue if the port went away */
- going = FALSE;
-
- /* Set the error message */
- ai->ai_Pri_Ret = RETURN_FAIL;
- ai->ai_Sec_Ret = MPERR_NO_PORT;
- ai->ai_TextRtn =
- PrepText (ai, APSH_USER_ID, ai->ai_Sec_Ret, NULL);
- }
-
- /* Go on to the next node */
- node = nxtnode;
- }
- }
- else
- {
- /* Send NEW */
- strcpy (md->md_Tmp, "NEW");
-
- /* Send the message */
- if (SafePutToPort ((struct Message *) msg, port_name))
- {
- /* wait for the reply */
- WaitPort (mp);
-
- /* Get the reply */
- GetMsg (mp);
- }
- }
-
- /* Free the message */
- FreeVec (msg);
- }
-
- /* Delete the reply port */
- DeletePort (mp);
- }
- }
-
- DI (kprintf ("IsActiveFunc exit\n"));
- }
-
- VOID SetAttrsFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
- {
- struct MasterData *md = (struct MasterData *) ai->ai_UserData;
- struct Project *p = &(ai->ai_Project);
- struct Funcs *f;
-
- if (f = af->af_FE)
- {
- /* Set the background bit? */
- if (f->fe_Options[0])
- {
- md->md_Flags |= MADF_BACKG;
- }
-
- /* Clear the background bit? */
- if (f->fe_Options[1])
- {
- md->md_Flags &= ~MADF_BACKG;
- }
- }
-
- /* See if we should quit */
- if ((p->p_NumProjs <= 0L) && !(md->md_Flags & MADF_BACKG))
- {
- ai->ai_Done = TRUE;
- }
- }
-
- /* Shutdown routine */
- VOID QuitFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
- {
- struct MasterData *md = (struct MasterData *) ai->ai_UserData;
- struct Project *p = &(ai->ai_Project);
- extern VOID QuitForce ();
- BOOL unload = FALSE;
- BOOL force = FALSE;
- struct Funcs *f;
-
- /* See if we have a parsed command */
- if (f = af->af_FE)
- {
- /* Did they set the force switch? */
- force = (BOOL) f->fe_Options[0];
-
- /* Are they trying to unload us? */
- if (unload = (BOOL) f->fe_Options[1])
- {
- md->md_Flags &= ~MADF_BACKG;
- }
- }
-
- if (force)
- {
- /* Tell all the projects to quit */
- signal_projects (ai, NULL, QuitForce);
- }
- else
- {
- /* Tell all the projects to quit */
- signal_projects (ai, SIGBREAKF_CTRL_C, NULL);
- }
-
- /* See if we should quit */
- if ((p->p_NumProjs <= 0L) && !(md->md_Flags & MADF_BACKG))
- {
- ai->ai_Done = TRUE;
- }
- }
-
- VOID QuitForce (struct AppInfo * ai, struct ProjData * pd)
- {
- /* Tell our master to open a new application */
- HandlerFunc (ai,
- APSH_Handler, "SIPC",
- APSH_Command, AH_SENDCMD,
- APSH_NameTag, pd->pd_Port,
- APSH_CmdString, (ULONG) "quit force",
- TAG_DONE);
- }
-
- /* Signal all projects */
- VOID signal_projects (struct AppInfo * ai, LONG sig, VOID (*func) (struct AppInfo *, struct ProjData *))
- {
- struct Project *p = &(ai->ai_Project);
- struct List *list = &(p->p_ProjList);
- struct ProjNode *pn;
- struct ProjData *pd;
- LONG key;
-
- /* Lock the master AppInfo */
- key = LockAppInfo (ai);
-
- /* Make sure there are entries in the list */
- if (list->lh_TailPred != (struct Node *) list)
- {
- struct Node *node, *nxtnode;
-
- /* Let's start at the very beginning... */
- node = list->lh_Head;
-
- /* Continue while there are still nodes */
- while (nxtnode = node->ln_Succ)
- {
- pn = (struct ProjNode *) node;
- pd = (struct ProjData *) pn->pn_UserData;
-
- if (sig)
- {
- /* Send a break signal to the project process */
- APSHSignal (pd->pd_AI, sig);
- }
-
- if (func)
- {
- (*(func)) (ai, pd);
- }
-
- /* Go on to the next node */
- node = nxtnode;
- }
- }
-
- /* Unlock the master AppInfo */
- UnlockAppInfo (key);
- }
-
- BOOL start_project (struct AppInfo * ai, struct ProjNode * pn)
- {
- struct MasterData *md = (struct MasterData *) ai->ai_UserData;
- struct Project *p = &(ai->ai_Project);
- extern struct TagItem Project_App[];
- struct ProjData *pd = NULL;
- struct TagItem tg[6];
- struct TagItem *clone;
- BOOL retval = FALSE;
- LONG key;
-
- /* Lock the AppInfo structure */
- key = LockAppInfo (ai);
-
- /* Set up our tags */
- tg[0].ti_Tag = APSH_AppHandle;
- tg[0].ti_Data = (ULONG) ai;
- tg[1].ti_Tag = APSH_ProjInfo;
- tg[2].ti_Tag = APSH_PortAddr;
- tg[2].ti_Data = (ULONG) md->md_SIPC;
- tg[3].ti_Tag = APSH_HookClass;
- tg[3].ti_Data = TRUE;
- tg[4].ti_Tag = TAG_MORE;
- tg[4].ti_Data = (ULONG) Project_App;
- tg[5].ti_Tag = TAG_DONE;
-
- /* Get a pointer to the project node */
- if (pn)
- {
- /* Set the current project */
- p->p_CurProj = pn;
-
- /* Pass the Project node */
- tg[1].ti_Data = (ULONG) pn;
-
- /* Clone the tag array */
- if (clone = CloneTagItems (tg))
- {
- if (pd = (struct ProjData *) AllocVec (sizeof (struct ProjData), MEMF_CLEAR))
- {
- /* Remember the clone, so that we can free it */
- pd->pd_Clone = clone;
-
- /* Attach the project data to the project node */
- pn->pn_UserData = pd;
-
- /* Make a nice unique process name */
- sprintf (md->md_Tmp, "%s.%ld", APPNAME, pn->pn_ID);
-
- /* Open a new project */
- if (HandlerFunc (ai,
- APSH_Handler, "TOOL",
- APSH_Command, APSH_MH_OPEN,
- APSH_Tool, (ULONG) md->md_Tmp,
- APSH_ToolData, (ULONG) clone,
- TAG_DONE))
- {
- /* Show success */
- retval = TRUE;
- }
- else
- {
- /* Unable to start the new process */
- ai->ai_Pri_Ret = RETURN_FAIL;
- ai->ai_Sec_Ret = MPERR_NO_PROCESS;
- ai->ai_TextRtn =
- PrepText (ai, APSH_USER_ID, ai->ai_Sec_Ret, NULL);
- }
- }
- else
- {
- /* Free the cloned tags */
- FreeTagItems (clone);
-
- /* Unable to allocate the project data node */
- ai->ai_Pri_Ret = RETURN_FAIL;
- ai->ai_Sec_Ret = MPERR_NO_MEMORY;
- ai->ai_TextRtn =
- PrepText (ai, APSH_USER_ID, ai->ai_Sec_Ret, NULL);
- }
- }
- else
- {
- /* Not enough memory to allocate tag list */
- ai->ai_Pri_Ret = RETURN_FAIL;
- ai->ai_Sec_Ret = MPERR_NO_MEMORY;
- ai->ai_TextRtn =
- PrepText (ai, APSH_USER_ID, ai->ai_Sec_Ret, NULL);
- }
- }
-
- /* Remove the lock */
- UnlockAppInfo (key);
-
- return (retval);
- }
-
- /* Send a message to the named message port */
- BOOL SafePutToPort (struct Message * message, STRPTR name)
- {
- struct MsgPort *port;
-
- Forbid ();
-
- if (port = FindPort (name))
- {
- PutMsg (port, message);
- }
-
- Permit ();
-
- return ((BOOL) port);
- }
-